﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PhantomRealm.Common.Utilities;
using System.Collections.Generic;
using Terraria;
using Terraria.GameContent;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Terraria.ID;
using Terraria.ModLoader;

namespace PhantomRealm.Content.NPCs.Enemies
{
    public class AuroraSlime : ModNPC
    {
        private float auroraTime;
        private readonly List<Vector2> positionHistory = [];
        private const int HISTORY_LENGTH = 5;
        private readonly Color AuroraColor1 = new(0, 143, 233);
        private readonly Color AuroraColor2 = new(0, 255, 255);
        private readonly Color AuroraColor3 = new(9, 231, 167);
        private readonly Color AuroraColor4 = new(0, 255, 100);

        public override void SetStaticDefaults()
        {
            Main.npcFrameCount[NPC.type] = Main.npcFrameCount[NPCID.BlueSlime];
        }

        public override void SetDefaults()
        {
            NPC.rarity = 1;
            NPC.width = 24;
            NPC.height = 18;
            NPC.aiStyle = NPCAIStyleID.Slime;
            NPC.damage = 7;
            NPC.defense = 2;
            NPC.lifeMax = 25;
            NPC.HitSound = SoundID.NPCHit1;
            NPC.DeathSound = SoundID.NPCDeath1;
            NPC.value = 25f;
            AIType = NPCID.BlueSlime;
            AnimationType = NPCID.BlueSlime;

            if (NPC.IsABestiaryIconDummy)
            {
                NPC.color = Color.Lerp(new Color(9, 231, 167), new Color(0, 255, 255),
                    (float)(System.Math.Sin(Main.GlobalTimeWrappedHourly * 2f) * 0.5f + 0.5f));
            }
        }

        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            bestiaryEntry.Info.AddRange([
                BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Times.NightTime,
                BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.Snow,
                new FlavorTextBestiaryInfoElement("Mods.PhantomRealm.NPCs.AuroraSlime.Description")
            ]);
        }

        public override float SpawnChance(NPCSpawnInfo spawnInfo)
        {
            if (spawnInfo.Player.ZoneSnow() && spawnInfo.Player.ZoneAurora() && spawnInfo.Player.IsNight())
            {
                return 0.12f;
            }
            return 0f;
        }

        public override void AI()
        {
            auroraTime += 0.05f;
            if (auroraTime > 1000f)
            {
                auroraTime = 0f;
            }

            if (NPC.IsABestiaryIconDummy)
            {
                NPC.color = Color.Lerp(new Color(9, 231, 167), new Color(0, 255, 255),
                    (float)(System.Math.Sin(Main.GlobalTimeWrappedHourly * 3f) * 0.5f + 0.5f));
            }

            if (!Main.gameMenu && !Main.dedServ && !NPC.IsABestiaryIconDummy)
            {
                UpdatePositionHistory();
            }
        }

        private void UpdatePositionHistory()
        {
            positionHistory.Insert(0, NPC.Center);
            if (positionHistory.Count > HISTORY_LENGTH)
            {
                positionHistory.RemoveAt(positionHistory.Count - 1);
            }
        }

        public override bool PreDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
        {
            if (NPC.IsABestiaryIconDummy)
            {
                return true;
            }
            DrawAuroraTrail(spriteBatch, screenPos);
            DrawAuroraBody(spriteBatch, screenPos);
            return false;
        }

        private void DrawAuroraBody(SpriteBatch spriteBatch, Vector2 screenPos)
        {
            Texture2D texture = TextureAssets.Npc[NPC.type].Value;
            Rectangle frame = NPC.frame;
            Vector2 origin = new Vector2(frame.Width * 0.5f, frame.Height * 0.5f);
            Vector2 drawPos = NPC.Center - screenPos;
            drawPos.Y += NPC.gfxOffY;

            spriteBatch.End();
            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive,
                Main.DefaultSamplerState, DepthStencilState.None,
                RasterizerState.CullNone, null, Main.GameViewMatrix.TransformationMatrix);

            for (int i = 0; i < 4; i++)
            {
                float timeOffset = auroraTime + i * 0.2f;
                float pulse = (float)System.Math.Sin(timeOffset * 2f) * 0.3f + 0.7f;
                float scaleMultiplier = 1.05f + i * 0.06f;
                float alpha = 0.6f / (i + 1) * pulse;

                Color gradientColor;
                switch (i)
                {
                    case 0:
                        gradientColor = AuroraColor3;
                        break;
                    case 1:
                        float blend1 = (float)System.Math.Sin(timeOffset * 1.5f) * 0.5f + 0.5f;
                        gradientColor = Color.Lerp(AuroraColor3, AuroraColor2, blend1);
                        break;
                    case 2:
                        float blend2 = (float)System.Math.Cos(timeOffset * 1.8f) * 0.5f + 0.5f;
                        gradientColor = Color.Lerp(AuroraColor3, AuroraColor1, blend2);
                        break;
                    default:
                        float blend3 = (float)System.Math.Sin(timeOffset * 2.2f) * 0.5f + 0.5f;
                        gradientColor = Color.Lerp(AuroraColor3, AuroraColor4, blend3);
                        break;
                }
                gradientColor.A = (byte)(alpha * 255);
                Vector2 offset = new((float)System.Math.Sin(timeOffset * 2f + i) * 1f, (float)System.Math.Cos(timeOffset * 1.5f + i) * 1f);
                spriteBatch.Draw(texture, drawPos + offset, frame, gradientColor, NPC.rotation, origin, NPC.scale * scaleMultiplier, SpriteEffects.None, 0f);
            }

            spriteBatch.End();
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend,
                Main.DefaultSamplerState, DepthStencilState.None,
                RasterizerState.CullNone, null, Main.GameViewMatrix.TransformationMatrix);
        }

        private void DrawAuroraTrail(SpriteBatch spriteBatch, Vector2 screenPos)
        {
            Texture2D texture = TextureAssets.Npc[NPC.type].Value;
            Rectangle frame = NPC.frame;
            Vector2 origin = new Vector2(frame.Width * 0.5f, frame.Height * 0.5f);

            for (int i = positionHistory.Count - 1; i >= 0; i--)
            {
                float progress = (float)i / HISTORY_LENGTH;
                float alpha = 0.6f * (1f - progress * progress);
                float scale = NPC.scale * (0.85f + 0.15f * progress);

                Color trailColor;
                if (progress < 0.33f)
                {
                    float blend = progress * 3f;
                    trailColor = Color.Lerp(AuroraColor3, AuroraColor2, blend);
                }
                else if (progress < 0.66f)
                {
                    float blend = (progress - 0.33f) * 3f;
                    trailColor = Color.Lerp(AuroraColor2, AuroraColor1, blend);
                }
                else
                {
                    float blend = (progress - 0.66f) * 3f;
                    trailColor = Color.Lerp(AuroraColor1, AuroraColor4, blend);
                }
                trailColor.A = (byte)(alpha * 255);
                Vector2 drawPos = positionHistory[i] - screenPos;
                drawPos.Y += NPC.gfxOffY;

                spriteBatch.Draw(texture, drawPos, frame, trailColor, NPC.rotation, origin, scale, SpriteEffects.None, 0f);
            }
        }

        public override void PostDraw(SpriteBatch spriteBatch, Vector2 screenPos, Color drawColor)
        {
            if (NPC.IsABestiaryIconDummy)
            {
                return;
            }
            DrawDynamicHighlights(spriteBatch, screenPos);
        }

        private void DrawDynamicHighlights(SpriteBatch spriteBatch, Vector2 screenPos)
        {
            Texture2D texture = TextureAssets.Npc[NPC.type].Value;
            Rectangle frame = NPC.frame;
            Vector2 origin = new(frame.Width * 0.5f, frame.Height * 0.5f);
            Vector2 drawPos = NPC.Center - screenPos;
            drawPos.Y += NPC.gfxOffY;

            float highlightTime = auroraTime * 2.5f;
            Color highlightColor;
            float phase = (float)System.Math.Sin(highlightTime) * 0.5f + 0.5f;
            if (phase < 0.25f)
                highlightColor = Color.Lerp(AuroraColor3, AuroraColor2, phase * 4f);
            else if (phase < 0.5f)
                highlightColor = Color.Lerp(AuroraColor2, AuroraColor1, (phase - 0.25f) * 4f);
            else if (phase < 0.75f)
                highlightColor = Color.Lerp(AuroraColor1, AuroraColor4, (phase - 0.5f) * 4f);
            else
                highlightColor = Color.Lerp(AuroraColor4, AuroraColor3, (phase - 0.75f) * 4f);

            highlightColor.A = 100;
            spriteBatch.Draw(texture, drawPos, frame, highlightColor,
                NPC.rotation, origin, NPC.scale * 1.03f, SpriteEffects.None, 0f);
        }

        public override void HitEffect(NPC.HitInfo hit)
        {
            if (NPC.life <= 0 && !NPC.IsABestiaryIconDummy)
            {
                for (int i = 0; i < 10; i++)
                {
                    Vector2 speed = new(Main.rand.NextFloat(-2f, 2f), Main.rand.NextFloat(-3f, -1f));
                    Color particleColor = (i % 4) switch
                    {
                        0 => AuroraColor1,
                        1 => AuroraColor2,
                        2 => AuroraColor3,
                        _ => AuroraColor4
                    };
                    Dust dust = Dust.NewDustPerfect(NPC.Center, DustID.Clentaminator_Blue, speed, 0, particleColor, 1.3f);
                    dust.noGravity = true;
                    dust.velocity *= 1.1f;
                }
            }
        }

        public override void DrawBehind(int index)
        {
            if (!NPC.IsABestiaryIconDummy)
            {
                float lightTime = auroraTime * 2f;
                Vector3 lightColor;
                float lightPhase = (float)System.Math.Sin(lightTime) * 0.5f + 0.5f;
                if (lightPhase < 0.33f)
                    lightColor = Vector3.Lerp(new Vector3(0.035f, 0.91f, 0.65f), new Vector3(0.0f, 1.0f, 1.0f), lightPhase * 3f);
                else if (lightPhase < 0.66f)
                    lightColor = Vector3.Lerp(new Vector3(0.0f, 1.0f, 1.0f), new Vector3(0.0f, 0.56f, 0.91f), (lightPhase - 0.33f) * 3f);
                else
                    lightColor = Vector3.Lerp(new Vector3(0.0f, 0.56f, 0.91f), new Vector3(0.0f, 1.0f, 0.39f), (lightPhase - 0.66f) * 3f);
                Lighting.AddLight(NPC.Center, lightColor * 0.7f);
            }
        }

        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ItemID.Gel, 1, 1, 3));
            npcLoot.Add(ItemDropRule.Common(ModContent.ItemType<Items.Materials.AuroraDust>(), 2, 1, 2));
        }
    }
}